package com.bjtu.ptsite.utils;

import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.concurrent.*;

/**
 * 异步任务工具
 */
public class TaskUtil {

    /**
     * 因为可能执行一些IO类任务，所以线程数据量应该是CPU数量的倍数。
     */
    private static final int DEFAULT_THREAD_SIZE = Runtime.getRuntime().availableProcessors() * 40 + 1;
    static ScheduledExecutorService executor = Executors.newScheduledThreadPool(DEFAULT_THREAD_SIZE, new CustomizableThreadFactory("TaskPool-"));

    /**
     * 延迟线程 延迟 MilliSeconds 毫秒执行 run
     *
     * @param milliSeconds 毫秒
     * @param run          执行的线程
     */
    public static ScheduledFuture<?> addTaskMilliSecond(long milliSeconds, Runnable run) {
        return executor.schedule(run, milliSeconds, TimeUnit.MILLISECONDS);
    }

    /**
     * 延迟线程 延迟 seconds 秒执行 run
     *
     * @param seconds 秒
     * @param run     执行的线程
     */
    public static void addTask(int seconds, Runnable run) {
        executor.schedule(run, seconds, TimeUnit.SECONDS);
    }

    /**
     * 延迟线程 延迟 minutes 分钟执行 run
     *
     * @param minutes 分钟
     * @param run     执行的线程
     */
    public static void addTaskMinutes(int minutes, Runnable run) {
        executor.schedule(run, minutes, TimeUnit.MINUTES);
    }

    /**
     * 固定间隔的循环线程 延迟 initialDelay 分钟，间隔 minutes 分钟 执行 run
     *
     * @param initialDelay 初始延迟 分钟
     * @param minutes      间隔 分钟
     * @param run          执行的线程
     */
    public static Future<?> addTaskAtFixedMinutesRate(int initialDelay, int minutes, Runnable run) {
        return executor.scheduleAtFixedRate(run, initialDelay, minutes, TimeUnit.MINUTES);
    }

    /**
     * 另开一条线程立即执行
     *
     * @param run 执行的线程
     */
    public static void execute(Runnable run) {
        executor.execute(run);
    }

    public static Future<?> submit(Runnable run) {
        return executor.submit(run);
    }

    /**
     * 尝试暂停所有线程
     */
    public static void shutdownNow() {
        TaskUtil.addTask(3, () -> {
            executor.shutdownNow();
        });
    }
}
